PostgreSQL 全文搜索 搜索结果排名

1 背景知识

PostgreSQL 按照 相似度 进行排序。排序的方法如下:
(1)词位频率:查询词在文档中出现频率。
(2)词位相似:查询词在文档中的词的相似度。
(3)词位权重:查询词出现的文档部分权重,并按照权重排序。

PostgreSQL提供了两种预定义的排名函数。

1.1 ts_rank函数

基于文档 匹配词位频率 进行排序。

ts_rank([ weights float4[], ] vector tsvector, query tsquery [, normalization integer ]) returns float4

1.2 ts_rank_cd 函数

类似于 ts_rank 函数,额外的还会匹配词位相似度。

ts_rank_cd([ weights float4[], ] vector tsvector, query tsquery [, normalization integer ]) returns float4

1.3 按照权重值排名

对这两个函数, weights 参数可以为词位标记的权重。指定单词的是否重要,按照如下的顺序:

{D-weight, C-weight, B-weight, A-weight}

例如:{1.0,2.0,3.0,4.0}
如果未填写 weights 参数,那么将使用默认值。

{0.1, 0.2, 0.4, 1.0}

1.4 根据文档的长度排名

因为文档越长包含 查询 的可能性将会越大,所以 排名 时需要考虑文档长度。例如
(1)A文档共100个词,匹配 查询 5次。
(2)B文档共1000个词,匹配 查询 也是5次。由于 B 文档比 A 文档更长,所以 A 文档的排名更靠前。

两个排名函数都采用一个整数 normalization 选项,指定文档长度是否参与到结果的排名顺序。此选项有下列多重含义:

参数 说明
0 默认值,忽略长度的影响。
1 log(rank/1 + doc_length)
2 rank / 1+ doc_length
4 rank/ doc_length_avg(只能用于 ts_rank_cd函数)。
8 rank/unique_count
16 log(rank/1+ unique_count)
32 rank/rank +1

由于此选项是一个位掩码配置:你可以使用 | 指定一个或多个行为(例如,2|4)。

2 根据相似度排名

SELECT title ,ts_rank(fulltext, to_tsquery('english', 'Woman')) AS rank
FROM film 
WHERE fulltext @@ to_tsquery('english', 'Woman')
ORDER BY rank DESC;
LIMIT 10;
//屏幕输出:
        title          |    rank     
------------------------+-------------
 MATRIX SNOWMAN         | 0.075990885
 HYDE DOCTOR            | 0.075990885
 STRANGER STRANGERS     | 0.075990885
 PLATOON INSTINCT       | 0.075990885
 TEMPLE ATTRACTION      | 0.075990885
 GLORY TRACY            | 0.075990885
 NOTORIOUS REUNION      |  0.06079271
 PACKER MADIGAN         |  0.06079271
 HUMAN GRAFFITI         |  0.06079271
 VANISHING ROCKY        |  0.06079271
 MULAN MOON             |  0.06079271
 ARSENIC INDEPENDENCE   |  0.06079271
 NOTTING SPEAKEASY      |  0.06079271
 OKLAHOMA JUMANJI       |  0.06079271
 NORTH TEQUILA          |  0.06079271
 MILLION ACE            |  0.06079271
 ANTITRUST TOMATOES     |  0.0607927
SELECT title ,ts_rank_cd(fulltext, to_tsquery('english', 'Woman')) AS rank
FROM film 
WHERE fulltext @@ to_tsquery('english', 'Woman')
ORDER BY rank DESC;
LIMIT 10;
//屏幕输出:
         title          | rank 
------------------------+------
 MATRIX SNOWMAN         |  0.2
 HYDE DOCTOR            |  0.2
 STRANGER STRANGERS     |  0.2
 PLATOON INSTINCT       |  0.2
 TEMPLE ATTRACTION      |  0.2
 GLORY TRACY            |  0.2
 NOTORIOUS REUNION      |  0.1
 PACKER MADIGAN         |  0.1
 HUMAN GRAFFITI         |  0.1
 VANISHING ROCKY        |  0.1
 MULAN MOON             |  0.1
 ARSENIC INDEPENDENCE   |  0.1

3 根据文档的长度排名

SELECT title, ts_rank_cd(fulltext, to_tsquery('english', 'Woman'), 32 /* rank/(rank+1) */ ) AS rank
FROM film
WHERE  to_tsquery('english', 'Woman') @@ fulltext
ORDER BY rank DESC
LIMIT 10;
         title         |    rank    
-----------------------+------------
 HYDE DOCTOR           | 0.16666667
 PLATOON INSTINCT      | 0.16666667
 STRANGER STRANGERS    | 0.16666667
 GLORY TRACY           | 0.16666667
 TEMPLE ATTRACTION     | 0.16666667
 MATRIX SNOWMAN        | 0.16666667
 NOTORIOUS REUNION     | 0.09090909
 WAIT CIDER            | 0.09090909
 CREATURES SHAKESPEARE | 0.09090909
 VANISHING ROCKY       | 0.09090909
(10 rows)